package org.mytools.dao.gener.meta;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.mytools.dao.gener.DomainWrapper;

public abstract class AbstarctMetaData implements MetaData {

	protected Connection connection = null;
	protected DatabaseMetaData databaseMetaData = null;

	public AbstarctMetaData(Connection connection) {
		this.connection = connection;
		try {
			this.databaseMetaData = connection.getMetaData();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public List<String> getTableNames() throws SQLException {
		ResultSet rest = this.databaseMetaData.getTables(null, null, null,
				new String[] { TABLE });

		List<String> tableNames = new ArrayList<String>();
		while (rest.next()) {
			tableNames.add(rest.getString(3));
		}
		this.close(rest);

		return tableNames;
	}

	@Override
	public List<String> getTableNames(String start) throws SQLException {
		List<String> tableNames = new ArrayList<String>();

		for (String name : this.getTableNames()) {
			if (name.startsWith(start)) {
				tableNames.add(name);
			}
		}

		return tableNames;
	}

	@Override
	public List<ColumnData> getColumns(ResultSetMetaData rsmd, String tableName)
			throws SQLException {
		List<ColumnData> columnMetas = new ArrayList<ColumnData>();
		List<ForeginKeys> fkslist = this.getForeginKeys(tableName);

		for (int i = 1; i <= rsmd.getColumnCount(); i++) {
			ColumnData columnMeta = new ColumnData();
			columnMeta.setSqlName(rsmd.getColumnName(i));
			columnMeta.setSqlTypeName(rsmd.getColumnTypeName(i));
			columnMeta.setColumnType(rsmd.getColumnType(i));
			columnMeta.setJavaTypeName(DomainWrapper.jdbcType2javaType(rsmd
					.getColumnType(i)));
			columnMeta.setJavaPropertyName(DomainWrapper
					.getDomainPropertyName(rsmd.getColumnName(i)));
			columnMeta.setAutoIncrement(rsmd.isAutoIncrement(i));
			columnMeta
					.setPk(this.isPrimaryKey(tableName, rsmd.getColumnName(i)));

			for (ForeginKeys fks : fkslist) {
				if (fks.getFkColumnName().equals(columnMeta.getSqlName())) {
					columnMeta.setFk(true);
					columnMeta.setForeginKeys(fks);
					break;
				}
			}

			columnMetas.add(columnMeta);
		}

		return columnMetas;
	}

	@Override
	public List<ColumnData> getColumns(String tableName) throws SQLException {
		PreparedStatement pstmt = null;
		ResultSet rest = null;
		StringBuffer sql = new StringBuffer(SELECT_TABLE);
		sql.append(tableName);
		sql.append(WHERE);

		pstmt = this.connection.prepareStatement(sql.toString());
		rest = pstmt.executeQuery();
		return getColumns(rest.getMetaData(), tableName);
	}

	@Override
	public boolean isPrimaryKey(String tableName, String columnName)
			throws SQLException {
		boolean isPk = false;

		List<String> pksList = this.getPKs(tableName);
		for (String pk : pksList) {
			if (pk.toUpperCase().equals(columnName.toUpperCase())) {
				isPk = true;
				break;
			}
		}

		return isPk;
	}

	public void close(ResultSet rest) {
		try {
			if (rest != null)
				rest.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}
